<template>
  <div class=""></div>
</template>

<script setup lang="ts">
  import { onMounted } from 'vue'
  // 类型别名
  type NewType = string | number
  let myFavoriteNumber: NewType = 'seven'
  myFavoriteNumber = 7

  // ======================================= 分割线 =======================================

  // 接口继承
  interface a {
    a: number
    b: string
  }
  interface b extends a {
    c: boolean
  }
  let obj: b = {
    a: 1,
    b: '2',
    c: true
  }

  // ======================================= 分割线 =======================================

  // TS中字符串索引带来的类型问题
  const typeObj = {
    name: '铁锤',
    age: 18
  }
  function typeObjfn(key: string) {
    const v = typeObj[key as keyof typeof typeObj]
    console.log(v, 'vvvvvvv')
  }
  typeObjfn('铁柱')

  // ======================================= 分割线 =======================================

  // 字面量类型
  type TypeSex = 'gril' | 'boy'
  let sex: TypeSex = 'gril'

  // ======================================= 分割线 =======================================

  // 泛型 指在定义函数、接口或类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性
  function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = []
    for (let i = 0; i < length; i++) {
      result.push(value)
    }
    console.log(result, '泛型')
    return result
  }
  createArray<string>(3, 'x') //也可以不手动指定类型，而让类型推论自动推算出来
  createArray<number>(3, 2)

  // 泛型 - 多个类型参数
  function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]]
  }
  console.log(swap([7, 'seven']), '泛型多类型参数')

  // 泛型约束
  interface Lengthwise {
    length: number
  }
  function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length)
    return arg
  }
  loggingIdentity('hello')

  // 泛型接口
  interface SearchFunc {
    (source: string, subString: string): boolean
  }
  let mySearch: SearchFunc
  mySearch = function (source: string, subString: string) {
    return source.search(subString) !== -1
  }
  console.log(mySearch('abc', 'b'), '普通接口定义函数类型')

  // 使用泛型接口定义函数类型
  interface CreateArrayFunc {
    <T>(length: number, value: T): Array<T>
  }
  let createArrayFn: CreateArrayFunc
  createArrayFn = function <T>(length: number, value: T): Array<T> {
    let result: T[] = []
    for (let i = 0; i < length; i++) {
      result[i] = value
    }
    return result
  }
  console.log(createArrayFn(3, 'y'), '使用泛型接口定义函数类型')

  // 泛型类
  class GenericNumber<T> {
    zeroValue: T = null as any
    add: (x: T, y: T) => T
  }

  let myGenericNumber = new GenericNumber<number>()
  myGenericNumber.zeroValue = 0
  myGenericNumber.add = function (x, y) {
    return x + y
  }

  // ======================================= 分割线 =======================================

  // Typescript的联合类型、Partial、Pick、Exclude、Omit介绍
  // Exclude (意思是排除) ts中可以排除 联合类型 中一部分的内容
  type myTypes = 'name' | 'age' | 'height'
  type someMyTypes = Exclude<myTypes, 'name'>
  const myTypes1: someMyTypes = 'age'
  const myTypes2: someMyTypes = 'name' //报错 不能将类型'name'分配给  'age' | 'height'

  // Partial (意思是部分的; 不完全的)，ts中就是让一个定义中的所有属性都变成可选参数
  interface Person {
    name: string
    age: number
  }
  // 但是有可能数据是请求过来的，所以刚开始我们需要定义一个对象
  const person1: Person = {} //报错
  const person2: Partial<Person> = {} //可以
  const person3: Partial<Person> = { name: '铁锤妹妹' } //可以
  const person4: Partial<Person> = { height: 170 } //报错

  // Pick （意思是选择）ts中可以选择一个原来的接口中一部分的属性定义
  type SomePerson1 = Pick<Person, 'name'> //选择单个属性
  type SomePerson2 = Pick<Person, 'name' | 'age'> //选择多个属性

  // Omit (意思是省略的) ts中就是将接口或者类型的键值对删除一部分
  const SomePerson3: Omit<Person, 'age'> = {
    name: '铁锤妹妹'
  }
  console.log(SomePerson3)

  onMounted(() => {})
</script>

<style lang="less" scoped></style>
